<template>
  <div class="page-container">
    <!--表格内容栏-->
    <cm-table
      ref="dataTable" 
      pkName="id" 
      :filters="filters"
      :filterFields="filterFields" 
      :columns="columns" 
      :defaultSort="defaultSort"
      @handleTableOperator="handleTableOperator"
    ></cm-table>

    <!--新增编辑界面-->
    <el-dialog
      :title="operator"
      width="500px"
      v-model="dialogVisible"
      :close-on-click-modal="false"
      append-to-body
      destroy-on-close
      draggable
    >
      <el-form
        :model="formData"
        label-width="120px"
        :rules="rules"
        ref="dataForm"
        label-position="right"
      >
        <el-row>
          <el-col :span="24">
            <el-form-item label="角色名称" prop="name">
              <el-input v-model="formData.name" auto-complete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="角色权力" prop="power">
              <el-input v-model="formData.power" auto-complete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button
          size="large"
          type="info"
          @click="dialogVisible = false"
        >取消</el-button>
        <el-button
          size="large"
          type="primary"
          @click="submitForm"
          :loading="editLoading"
        >提交</el-button>
      </template>
    </el-dialog>

    <el-dialog
      :title="operator"
      width="90%"
      v-model="dialogPoVisible"
      :close-on-click-modal="false"
      class="privilege-dialog"
      destroy-on-close
      fullscreen
    >
      <el-table
        :prop="formPoCheckData"
        :data="formPoCheckData"
        :show-overflow-tooltip="true"
        tooltip-effect="light"
        border
        :span-method="objectOneMethod"
      >
        <el-table-column
          prop="first"
          label="一级菜单"
          header-align="center"
          align="left"
          :show-overflow-tooltip="true"
        >
          <template v-slot="scope">
            <el-checkbox :label="scope.row.first"
              v-model="formPoData.labels[scope.row.first]"
              @change="changeCheckBox($event, scope.row, 1)"
            ></el-checkbox>
          </template>
        </el-table-column>
        <el-table-column
          prop="second"
          label="二级菜单"
          header-align="center"
          align="left"
          :show-overflow-tooltip="true"
        >
          <template v-slot="scope">
            <el-checkbox
              v-if="scope.row.second!==''"
              :label="scope.row.second"
              v-model="formPoData.labels[scope.row.first + '--' + scope.row.second]"
              @change="changeCheckBox($event, scope.row, 2)"
            ></el-checkbox>
          </template>
        </el-table-column>
        <el-table-column
          prop="third" label="三级菜单"
          header-align="center"
          align="left"
          :show-overflow-tooltip="true"
        >
          <template v-slot="scope">
            <el-checkbox
              v-if="scope.row.third!==''"
              :label="scope.row.third"
              v-model="formPoData.labels[scope.row.first + '--' + scope.row.second + '--' + scope.row.third]"
              @change="changeCheckBox($event, scope.row, 3)"
            ></el-checkbox>
          </template>
        </el-table-column>
        <el-table-column
          min-width="340"
          prop="children"
          label="权限"
          header-align="center"
          align="left"
        >
          <template v-slot="scope">
            <el-checkbox-group v-model="formPoData.privilegeIds" class="check-box">
              <el-checkbox :label="scope.row.thirdId + '--0'" key="0">读取</el-checkbox>
              <el-checkbox v-for="children in scope.row.children"
                :label="scope.row.thirdId + '--' + children.id"
                :key="children.id"
              >
                {{children.text}}
              </el-checkbox>
            </el-checkbox-group>
          </template>
        </el-table-column>
      </el-table>
      <template #footer>
        <el-button
          size="large"
          type="info"
          @click="dialogPoVisible = false"
        >取消</el-button>
        <el-button
          size="large"
          type="primary"
          @click="submitPoForm"
          :loading="editPoLoading"
        >提交</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref, nextTick} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import api from '@/http/api'

const filters = ref({ name: '' })
const filterFields = ref([
  {prop: "name", label: "角色名称"},
])
const columns = ref([
  {prop: "name", label: "角色名称", minWidth: 200},
  {prop: "power", label: "角色权力", minWidth: 350, type: 'number'}
])
const operator = ref('')
const loading = ref(false)
const dialogVisible = ref(false)
const dialogPoVisible = ref(false)
const editLoading = ref(false)
const editPoLoading = ref(false)
const formData = ref({
  id: '',
  name: '',
  power: ''
})
const formPoData = ref({labels: []})
const formPoCheckData = ref([])
const rules = ref({
  name: [{required: true, message: '请输入角色名称', trigger: 'blur'}],
  power: [{required: true, message: '请输入角色权力', trigger: 'blur'}]
})
const defaultSort = ref({prop: 'power', order: 'ascending'})
const dataForm = ref()
const dataTable = ref()

const changeCheckBox = (checked, item, depth) => {
  let data = [];
  let labels = [];
  if (depth === 1) {
    for (let i=0;i<formPoCheckData.value.length;i++) {
      if (formPoCheckData.value[i].first === item.first) {
        labels.push(formPoCheckData.value[i].first);
        labels.push(formPoCheckData.value[i].first + '--' + formPoCheckData.value[i].second);
        labels.push(formPoCheckData.value[i].first
          + '--' + formPoCheckData.value[i].second
          + '--' + formPoCheckData.value[i].third);
        data = data.concat(getCheckData(formPoCheckData.value[i]));
      }
    }
  } else if (depth === 2) {
    for (let j=0;j<formPoCheckData.value.length;j++) {
      if (formPoCheckData.value[j].first === item.first
          && formPoCheckData.value[j].second === item.second) {
        labels.push(formPoCheckData.value[j].first + '--' + formPoCheckData.value[j].second);
        labels.push(formPoCheckData.value[j].first
          + '--' + formPoCheckData.value[j].second
          + '--' + formPoCheckData.value[j].third);
        data = data.concat(getCheckData(formPoCheckData.value[j]));
      }
    }
  } else if (depth === 3) {
    for (let k=0;k<formPoCheckData.value.length;k++) {
      if (formPoCheckData.value[k].first === item.first
          && formPoCheckData.value[k].second === item.second
          && formPoCheckData.value[k].third === item.third) {
        labels.push(formPoCheckData.value[k].first
          + '--' + formPoCheckData.value[k].second
          + '--' + formPoCheckData.value[k].third);
        data = data.concat(getCheckData(formPoCheckData.value[k]));
      }
    }
  }

  if (checked) {
    formPoData.value.privilegeIds = uniqueArr(formPoData.value.privilegeIds.concat(data));
    for (let n=0; n<labels.length; n++) {
      formPoData.value.labels[labels[n]] = true;
    }
  } else {
    formPoData.value.privilegeIds = deleteArr(formPoData.value.privilegeIds, data);
    for (let m=0;m<labels.length;m++) {
      formPoData.value.labels[labels[m]] = false;
    }
  }
}

const getCheckData = (item) => {
  let data = [];
  if (item.children.length > 0) {
    for (let i=0; i<item.children.length; i++) {
      data = data.concat(getCheckData(item.children[i]));
    }
  } else {
    if (item.pid && item.id) {
      data.push(item.pid + '--' + item.id);
    }
  }
  if (item.thirdId) {
    data.push(item.thirdId + '--0');
  }
  return data;
}

const uniqueArr = (array) => {
  let temp = []; //一个新的临时数组
  for(let i = 0; i < array.length; i++){
    if(temp.indexOf(array[i]) === -1){
      temp.push(array[i]);
    }
  }
  return temp;
}

const deleteArr = (arr, brr) => {
  for(let i=0; i<brr.length; i++){
    for(let j=0; j<arr.length; j++){
      if(arr[j] === brr[i]){
        arr.splice(j,1);
        j--;
      }
    }
  }
  return arr;
}

// 显示操作界面
const handleTableOperator = (button, row) => {
  operator.value = button.name
  if (button.buttonType === 'edit') {
    formData.value = Object.assign({}, row, {button: button})
  } else if (button.buttonType === 'editPo') {
    formPoCheckData.value = [];
    formPoData.value = Object.assign({}, {id: row.id, labels: [], privilegeIds: []}, {button: button});
    loading.value = true
    dialogPoVisible.value = true
    api.post(button.dataSourUrl, {id: row.id}).then(res => {
      loading.value = false
      formPoCheckData.value = res.data.menus
      formPoData.value = Object.assign({},
        {id: row.id, labels: [], privilegeIds: res.data.privilegeIds}, {button: button}
      );

      let labels = [];
      for (let i=0;i<formPoCheckData.value.length;i++) {
        labels.push(formPoCheckData.value[i].first);
        labels.push(formPoCheckData.value[i].first + '--' + formPoCheckData.value[i].second);
        labels.push(formPoCheckData.value[i].first
          + '--' + formPoCheckData.value[i].second + '--' + formPoCheckData.value[i].third);
      }
      for (let j=0;j<labels.length;j++) {
        formPoData.value.labels[labels[j]] = false;
      }
    }).catch(() => {
      loading.value = false
    })
    return;
  } else {
    formData.value = {button: button};
  }

  dialogVisible.value = true
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
};

// 角色菜单操作保存
const submitPoForm = () => {
  ElMessageBox.confirm('请确认是否提交？', '提示', {type: 'info'}).then(() => {
    editPoLoading.value = true
    api.post(formPoData.value.button.dataDestUrl, formPoData.value).then(res => {
      ElMessage.success(res.message);
      dialogPoVisible.value = false;
      editPoLoading.value = false;
    }).catch(() => {
      editPoLoading.value = false;
    })
  }).catch(()=>{});
};

const setTable = (tableData) => {
  let spanOneArr = [], spanTwoArr = [], concatOne = 0, concatTwo = 0;
  tableData.forEach((item, index) => {
    if(index === 0){
      spanOneArr.push(1);
      spanTwoArr.push(1);
    }else{
      if(item.first === tableData[index - 1].first){ //第一列需合并相同内容的判断条件
        spanOneArr[concatOne] += 1;
        spanOneArr.push(0);
      }else{
        spanOneArr.push(1);
        concatOne = index;
      }
      //第二列和第16列需合并相同内容的判断条件
      if(item.second === tableData[index - 1].second && (item.second || '') !== ''){
        spanTwoArr[concatTwo] += 1;
        spanTwoArr.push(0);
      }else{
        spanTwoArr.push(1);
        concatTwo = index;
      }
    }
  });
  return  {
    one: spanOneArr,
    two: spanTwoArr
  }
};

const objectOneMethod = ({ row, column, rowIndex, columnIndex }) => {
  if(columnIndex === 0 ) {
    const _row = (setTable(formPoCheckData.value).one)[rowIndex];
    const _col = _row > 0 ? 1 : 0;
    return {
      rowspan: _row,
      colspan: _col,
      _row: row,
      _column: column
    };
  }
  if(columnIndex === 1 || columnIndex === 15) {
    const _row = (setTable(formPoCheckData.value).two)[rowIndex];
    const _col = _row > 0 ? 1 : 0;
    return {
      rowspan: _row,
      colspan: _col
    };
  }
};

const submitForm = () => {
  dataForm.value && dataForm.value.validate((valid) => {
    if (valid) {
      ElMessageBox.confirm('请确认是否提交？', '提示', {type: 'info'}).then(() => {
        editLoading.value = true
        api.post(formData.value.button.dataDestUrl, formData.value).then((res) => {
          ElMessage.success(res.message);
          dialogVisible.value = false;
          dataTable.value.findPage()
          editLoading.value = false;
        }).catch(() => {
          editLoading.value = false;
        });
      }).catch(()=>{});
    }
  })
};
</script>

<style scoped>
.operator-dialog :deep(.el-table td .cell) {
  padding-left: 10px;
}
.operator-dialog :deep(.el-table td .el-checkbox-group) {
  white-space: normal;
}

.table-container :deep(.el-table){
  height: calc(100vh - 240px)!important;
}
.table-container :deep(.tree-col){
  height: calc(100vh - 240px)!important;
}
.privilege-dialog .check-box {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
</style>